package com.fushenlan.epidemicControl.aspect;

import com.fushenlan.commons.AspectUtils;
import com.fushenlan.epidemicControl.annotation.MarketCache;
import com.fushenlan.epidemicControl.service.IMarketCacheService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @author PC
 * @title: MarketCacheAspect
 * @projectName SpringBootDemo
 * @description: TODO
 * @date 2022/1/20 16:30
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
@Aspect
@Component("marketCache")
@Slf4j
public class MarketCacheAspect {

    @Value("${userCache.market:true}")
    private Boolean useCache;
    @Autowired
    private IMarketCacheService marketCacheService;

    @Pointcut("@annotation(com.fushenlan.epidemicControl.annotation.MarketCache)")
    public void marketCache() {

    }

    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        if (!useCache) {
            return joinPoint.proceed(joinPoint.getArgs());
        }
        Object result;
        Method method = AspectUtils.getMethod(joinPoint);
        MarketCache marketCache = method.getAnnotation(MarketCache.class);
        if (marketCache.cacheKeyPrefix() != null) {
            Map<String, Object> methodParamMap = AspectUtils.getParamMap(joinPoint);
            String key = getKey(methodParamMap);
            Object redisCache = marketCacheService.getCache(marketCache.cacheKeyPrefix(), key);
            if (redisCache != null) {
                return redisCache;
            }
            result = joinPoint.proceed(joinPoint.getArgs());
            marketCacheService.cacheResponse(marketCache.cacheKeyPrefix(), key, result, marketCache.cacheSeconds());
        } else {
            result = joinPoint.proceed(joinPoint.getArgs());
        }
        return result;
    }

    private String getKey(Map<String, Object> methodParamMap) {
        String methodParamMapStr = String.valueOf(methodParamMap);
        log.info("=======> Params : {}", methodParamMapStr);
        return DigestUtils.md5DigestAsHex(methodParamMapStr.getBytes(StandardCharsets.UTF_8));
    }
}
